package cn.com.doone.common.uc.oauth.shiro;

import java.security.SecureRandom;
import java.util.Hashtable;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import javax.naming.Context;
import javax.naming.NamingException;
import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;
import javax.naming.directory.BasicAttribute;
import javax.naming.directory.BasicAttributes;
import javax.naming.ldap.InitialLdapContext;
import javax.naming.ldap.LdapContext;

import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.credential.SimpleCredentialsMatcher;

import cn.com.doone.common.uc.utils.MD5;

public class OAuth2DooneCredentialsMatcher extends SimpleCredentialsMatcher {
	
	/*@Autowired
	private OauthJdbcRepository oauthJdbcRepository;*/
	
	@Override  
    public boolean doCredentialsMatch(AuthenticationToken token,  AuthenticationInfo info) {  
        Object tokenCredentials = encode(toString(token.getCredentials()));  
        Object accountCredentials = getCredentials(info);
        
        boolean isEquals = equals(tokenCredentials, accountCredentials);
        
        /*if (isEquals) {
        	System.out.println("同步至LDAP测试库");
        	LdapContext ldapContext = null;
        	try {
				ldapContext = getContext();
				
				List<Map<String, Object>> userList = oauthJdbcRepository.findUserInfo();
				
				for (Map<String, Object> userMap : userList) {
					
					try {
						addUser(ldapContext, (String) userMap.get("userAccount"), "1q2w3E4R", "OU=Account,DC=doone,DC=com,DC=cn", (String) userMap.get("realname"));
					} catch (Exception e) {
						e.printStackTrace();
						oauthJdbcRepository.addUserInfo((String) userMap.get("userAccount"), (String) userMap.get("realname"));;
					}
					
				}
				
				// addUser(ldapContext, "test9", "1q2w3E4R", "OU=新东网科技,DC=doone,DC=com,DC=cn", "士大夫");
			} catch (NamingException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} finally {
	            LdapUtils.closeContext(ldapContext);
	        }
        }*/
        
        return isEquals;  
    }
	
	/**
	 * 旧OA加密算法
	 * 
	 * @param password
	 * @return
	 */
	 private byte[] encode(String password) {
		// TODO Auto-generated method stub
		String ret = "";
	    ret = MD5.getMD5Str(password);
	    ret = ret.substring(8, 24);
		
	    
		return ret.getBytes();
	}

	private byte[] encrypt(byte[] data) {  
        try {  
            byte[] key = "11111111".getBytes();  
  
            // DES算法要求有一个可信任的随机数源  
  
            SecureRandom sr = new SecureRandom();  
  
            // 从原始密钥数据创建DESKeySpec对象  
            DESKeySpec dks = new DESKeySpec(key);  
  
            // 创建一个密匙工厂，然后用它把DESKeySpec转换成  
  
            // 一个SecretKey对象  
  
            SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");  
  
            SecretKey secretKey = keyFactory.generateSecret(dks);  
  
            // using DES in ECB mode  
  
            Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");  
  
            // 用密匙初始化Cipher对象  
  
            cipher.init(Cipher.ENCRYPT_MODE, secretKey, sr);  
  
            // 执行加密操作  
  
            byte encryptedData[] = cipher.doFinal(data);  
  
            return encryptedData;  
  
        } catch (Exception e) {  
  
            System.err.println("DES算法，加密数据出错!");  
  
            e.printStackTrace();  
  
        }  
        return null;  
    }
	
	/**
	 * 以下都是同步LDAP数据的方法
	 */
	
	public static void main(String [] args) throws NamingException {
			
		LdapContext ldapContext = getContext();
		// searchOU(ldapContext);
		// searchUserByOU(ldapContext);
		// addUser(ldapContext, "test9", "1q2w3E4R", "OU=新东网科技,DC=doone,DC=com,DC=cn", "士大夫");
		// updateUser(ldapContext, "test2", "OU=租户一,DC=doone,DC=com,DC=cn");
		// deleteUser(ldapContext, "test2", "OU=租户一,DC=doone,DC=com,DC=cn");
		// updatePassword(ldapContext, "test3", "1q2w3E4R", "OU=租户一,DC=doone,DC=com,DC=cn");;
		// addOU(ldapContext, "租户二", "DC=doone,DC=com,DC=cn");
		// deleteOU(ldapContext, "租户二", "DC=doone,DC=com,DC=cn");
		
	}
	private static void addUser(LdapContext ldapContext, String userName, String password, String dn, String realname) throws Exception {
	
			String distinguishedName = "CN=" + userName + "," + dn;   
            Attributes newAttributes = new BasicAttributes(true);   
            Attribute oc = new BasicAttribute("objectClass");
            
            oc.add("top");   
            oc.add("account");
            oc.add("xdwAccount");
            newAttributes.put(oc);   
            newAttributes.put(new BasicAttribute("uid", userName));   
            newAttributes.put(new BasicAttribute("displayName", realname));
            newAttributes.put(new BasicAttribute("cn", realname));
            newAttributes.put(new BasicAttribute("userPassword", "cb8e30682b927f35"));
            newAttributes.put(new BasicAttribute("ou", "doone.com.cn"));
            ldapContext.createSubcontext(distinguishedName, newAttributes);
		

	}
	
	private static LdapContext getContext() throws NamingException {
		
		Hashtable<String, String> ldapEnv = new Hashtable<String, String>(11);
		ldapEnv.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
		ldapEnv.put(Context.PROVIDER_URL,  "ldap://192.168.100.133:389");
		// ldapEnv.put(Context.PROVIDER_URL, "ldaps://192.168.100.70:636");
		ldapEnv.put(Context.SECURITY_AUTHENTICATION, "simple");
		ldapEnv.put(Context.SECURITY_PRINCIPAL, "cn=Users,dc=doone,dc=com,dc=cn");
		// ldapEnv.put(Context.SECURITY_PRINCIPAL, "root");
		ldapEnv.put(Context.SECURITY_CREDENTIALS, "1q2w3E4R");
		// ldapEnv.put(Context.SECURITY_PROTOCOL, "ssl");
		// ldapEnv.put(Context.REFERRAL, "follow");
		
		return new InitialLdapContext(ldapEnv, null);
	}
	
}
